home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vbalyz / mfuncs.bas < prev    next >
Encoding:
BASIC Source File  |  1995-01-05  |  20.8 KB  |  840 lines

  1. Option Explicit
  2.  
  3. Global Const APP_NAME = "VB*Alyzer"
  4.  
  5. Dim mblnProjectSelected As Integer
  6. Dim mstrProjectName  As String
  7.  
  8. Dim mstraProjFile() As String
  9.  
  10. Type Metric_Type
  11.     Name As String
  12.     LongName As String
  13.     Display As Integer
  14. End Type
  15.  
  16. Dim muaMetric(1 To 20) As Metric_Type
  17.  
  18. Type FileStats_Type
  19.     Filename As String
  20.     Metric(1 To 20)  As Single
  21.     CurrentBeginEndLevel As Integer
  22.     CurrentFunc As String
  23.     CurrentComplexity As Integer
  24.     WorstRoutine As String
  25. End Type
  26.  
  27. Type Status_Type
  28.     InRoutine As Integer
  29.     InType As Integer
  30. End Type
  31.  
  32. Dim muStatus As Status_Type
  33.  
  34. Const TOTSIZE = 1
  35. Const TOTLINES = 2
  36. Const BLANKLINES = 3
  37. Const TOTCOMMENTS = 4
  38. Const TOTROUTINES = 5
  39. Const PRIVATEROUTINES = 6
  40. Const LOCALVARS = 7
  41. Const LOCALCONSTS = 8
  42. Const MODULEVARS = 9
  43. Const MODULECONSTS = 10
  44. Const GLOBALVARS = 11
  45. Const GLOBALCONSTS = 12
  46. Const APIDECS = 13
  47. Const TYPES = 14
  48. Const TYPELINES = 15
  49. Const AVERTNLINES = 16
  50. Const RTNNONCODELINES = 17
  51. Const ROUTINECODELINES = 18
  52. Const ROUTINEDECPTS = 19
  53. Const MOSTCOMPLEX = 20
  54.  
  55. Dim muTotStat As FileStats_Type
  56.  
  57. Sub AccumTotals (uStatIn As FileStats_Type)
  58.  
  59. ' Add the values in the supplied stat record to the total record
  60.  
  61. Dim i As Integer
  62.  
  63.     For i = LBound(uStatIn.Metric) To UBound(uStatIn.Metric)
  64.         If i <> MOSTCOMPLEX Then
  65.             muTotStat.Metric(i) = muTotStat.Metric(i) + uStatIn.Metric(i)
  66.         Else
  67.             ' MostComplex should be a maximum
  68.             If muTotStat.Metric(i) < uStatIn.Metric(i) Then
  69.                 muTotStat.Metric(i) = uStatIn.Metric(i)
  70.             End If
  71.         End If
  72.     Next
  73.  
  74. End Sub
  75.  
  76. Sub AnalyzeCurrentProject (lst As Control, grd As Grid)
  77.  
  78. Dim i As Integer
  79.  
  80.     Screen.MousePointer = HOURGLASS
  81.  
  82.     ' Reset output grid
  83.     ClearWholeGrid grd
  84.     grd.Rows = 1
  85.     SetGridHeadings grd
  86.  
  87.     ZeroProjectTotals
  88.  
  89.     ' For each file in list, take it apart
  90.     For i = 0 To lst.ListCount - 1
  91.         AnalyzeFile lst.List(i), grd
  92.     Next
  93.  
  94.     ' Display stats
  95.     ReportStats muTotStat, grd
  96.  
  97.     Screen.MousePointer = DEFAULT
  98.  
  99. End Sub
  100.  
  101. Sub AnalyzeFile (ByVal strFile As String, grd As Grid)
  102.  
  103. Dim intF As Integer
  104. Dim strLine As String
  105. Dim uStat As FileStats_Type
  106.  
  107.     intF = FreeFile
  108.  
  109.     Open strFile For Input As intF
  110.  
  111.     muStatus.InRoutine = False
  112.     uStat.Filename = strFile
  113.  
  114.     Do
  115.         Line Input #intF, strLine
  116.         AnalyzeLine strLine, uStat
  117.     Loop Until EOF(intF)
  118.  
  119.     ' Check last routine's complexity
  120.     If muStatus.InRoutine Then
  121.         CheckComplexity uStat, strLine
  122.     End If
  123.  
  124.     Close intF
  125.  
  126.     ReportStats uStat, grd
  127.  
  128.     AccumTotals uStat
  129.  
  130. End Sub
  131.  
  132. Sub AnalyzeLine (ByVal strLine As String, uStat As FileStats_Type)
  133.  
  134. ' This is the main engine for the whole metric part of the program
  135. ' It's not very nice, and should probably be broken up. Sooner rather
  136. ' than later.
  137.  
  138.     ' Add Line lingth to total size
  139.     uStat.Metric(TOTSIZE) = uStat.Metric(TOTSIZE) + Len(strLine)
  140.     
  141.     ' Remove leading/trailing spaces
  142.     strLine = Trim$(strLine)
  143.  
  144.     ' If working on a form, ignore control description info,
  145.     ' identifiable by "Begin" and "End". Keep track of current
  146.     ' "level": while > 0 we're still working in the uninteresting
  147.     ' part of the file.
  148.     If Right$(uStat.Filename, 3) = "FRM" Then
  149.         If IsLeftEnd(strLine, "Begin") Then
  150.             uStat.CurrentBeginEndLevel = uStat.CurrentBeginEndLevel + 1
  151.             Exit Sub
  152.         End If
  153.         If uStat.CurrentBeginEndLevel > 0 Then
  154.             If IsLeftEnd(strLine, "End") Then
  155.                 uStat.CurrentBeginEndLevel = uStat.CurrentBeginEndLevel - 1
  156.                 Exit Sub
  157.             End If
  158.         End If
  159.         If uStat.CurrentBeginEndLevel > 0 Then
  160.             Exit Sub
  161.         End If
  162.     End If
  163.  
  164.     ' Increment total lines
  165.     inc uStat, TOTLINES
  166.     
  167.     ' If blank line, increment blank count
  168.     If Len(strLine) = 0 Then
  169.         inc uStat, BLANKLINES
  170.         ' If blank is in a routine, increment non-code line count
  171.         If muStatus.InRoutine Then
  172.             inc uStat, RTNNONCODELINES
  173.         End If
  174.         Exit Sub
  175.     End If
  176.  
  177.     ' If comment... (Note no allowance made for trailing comments)
  178.     If Left$(strLine, 1) = "'" Then
  179.         inc uStat, TOTCOMMENTS
  180.         If muStatus.InRoutine Then
  181.             inc uStat, RTNNONCODELINES
  182.         End If
  183.         Exit Sub
  184.     End If
  185.  
  186.     If IsLeftEnd(strLine, "Private") Then
  187.         inc uStat, PRIVATEROUTINES
  188.         StripLeftmostWord strLine
  189.     End If
  190.  
  191.     ' Check current line for being a routine (= Sub or Function)
  192.     If IsRoutine(strLine) Then
  193.         
  194.         muStatus.InRoutine = True
  195.         inc uStat, TOTROUTINES
  196.     
  197.         CheckComplexity uStat, strLine
  198.  
  199.         ' Uses McCabe complexity metric, counting decision points.
  200.         ' A routine's Decision Pt count is always 1, even if
  201.         ' there's nothing else of significance in the routine
  202.         inc uStat, ROUTINEDECPTS
  203.         uStat.CurrentComplexity = 1
  204.  
  205.         ' Get routine name by removing the Sub or Function part...
  206.         StripLeftmostWord strLine
  207.  
  208.         ' ...and taking the next word
  209.         uStat.CurrentFunc = LeftMostWord(strLine)
  210.         
  211.         Exit Sub
  212.     End If
  213.  
  214.     ' Are we defining a variable?
  215.     If IsLeftEnd(strLine, "Dim") Then
  216.         If muStatus.InRoutine Then
  217.             inc uStat, LOCALVARS
  218.             inc uStat, RTNNONCODELINES
  219.         Else
  220.             inc uStat, MODULEVARS
  221.         End If
  222.         Exit Sub
  223.     End If
  224.  
  225.     ' How about a Constant?
  226.     If IsLeftEnd(strLine, "Const") Then
  227.         If muStatus.InRoutine Then
  228.             inc uStat, LOCALCONSTS
  229.             inc uStat, RTNNONCODELINES
  230.         Else
  231.             inc uStat, MODULECONSTS
  232.         End If
  233.         Exit Sub
  234.     End If
  235.  
  236.     ' Is something being defined globally?
  237.     If IsLeftEnd(strLine, "Global") Then
  238.         ' Is it a constant?
  239.         If InStr(strLine, " Const ") Then
  240.             inc uStat, GLOBALCONSTS
  241.         Else
  242.         ' If not, it must be a variable of some sort
  243.             inc uStat, GLOBALVARS
  244.         End If
  245.         Exit Sub
  246.     End If
  247.  
  248.     ' Check for API declarations (includes all DLL links)
  249.     If IsLeftEnd(strLine, "Declare Sub") Or IsLeftEnd(strLine, "Declare Function") Then
  250.         inc uStat, APIDECS
  251.         Exit Sub
  252.     End If
  253.  
  254.     ' If we're not currently processing a Type, then check to see
  255.     ' if one's just turned up...
  256.     If Not muStatus.InType Then
  257.         ' If it has, then record the fact
  258.         If IsLeftEnd(strLine, "Type") Then
  259.             muStatus.InType = True
  260.             inc uStat, TYPES
  261.             Exit Sub
  262.         End If
  263.     End If
  264.  
  265.     ' if we're in a Type declaration,
  266.     If muStatus.InType Then
  267.         ' Check for the end of it
  268.         If IsLeftEnd(strLine, "End Type") Then
  269.             muStatus.InType = False
  270.             inc uStat, TYPELINES
  271.         Else
  272.             inc uStat, TYPELINES
  273.         End If
  274.         Exit Sub
  275.     End If
  276.  
  277.     ' If we're in a routine, check this line for decision
  278.     ' points.
  279.     If muStatus.InRoutine Then
  280.         CountDecisionPoints strLine, uStat
  281.         ' Since we've got this far, and exited earlier if
  282.         ' non-"action code" lines were encountered, it's a
  283.         ' reasonable bet that this line _is_ "action code"
  284.         inc uStat, ROUTINECODELINES
  285.     End If
  286.  
  287. End Sub
  288.  
  289. Sub CheckComplexity (uStat As FileStats_Type, strLine As String)
  290.  
  291.     ' if in a routine, check to see if the last routine was more complex
  292.     ' than that currently stored
  293.     If muStatus.InRoutine Then
  294.         If uStat.CurrentComplexity > uStat.Metric(MOSTCOMPLEX) Then
  295.             uStat.Metric(MOSTCOMPLEX) = uStat.CurrentComplexity
  296.             uStat.WorstRoutine = uStat.CurrentFunc
  297.         End If
  298.     End If
  299.  
  300. End Sub
  301.  
  302. Sub ClearProjectFileList ()
  303.  
  304.     ReDim mstraProjFile(1 To 1)
  305.  
  306. End Sub
  307.  
  308. Sub CountDecisionPoints (ByVal strLine As String, uStat As FileStats_Type)
  309.  
  310. Dim intDecPts As Integer
  311.  
  312.     ' Check for lines beginning Select Case/For/Do/While
  313.     If IsLeftEnd(strLine, "Select Case") Then
  314.         inc uStat, ROUTINEDECPTS
  315.         uStat.CurrentComplexity = uStat.CurrentComplexity + 1
  316.         Exit Sub
  317.     End If
  318.     
  319.     If IsLeftEnd(strLine, "For") Then
  320.         inc uStat, ROUTINEDECPTS
  321.         uStat.CurrentComplexity = uStat.CurrentComplexity + 1
  322.         Exit Sub
  323.     End If
  324.     
  325.     If IsLeftEnd(strLine, "Do") Then
  326.         inc uStat, ROUTINEDECPTS
  327.         uStat.CurrentComplexity = uStat.CurrentComplexity + 1
  328.         Exit Sub
  329.     End If
  330.     
  331.     If IsLeftEnd(strLine, "While") Then
  332.         inc uStat, ROUTINEDECPTS
  333.         uStat.CurrentComplexity = uStat.CurrentComplexity + 1
  334.         Exit Sub
  335.     End If
  336.     
  337.     ' with Ifs and ElseIfs, check also for Ands and Ors
  338.     If IsLeftEnd(strLine, "If") Or IsLeftEnd(strLine, "ElseIf") Then
  339.     
  340.         inc uStat, ROUTINEDECPTS
  341.         strLine = Trim$(Mid$(strLine, 3))
  342.         uStat.CurrentComplexity = uStat.CurrentComplexity + 1
  343.     
  344.         intDecPts = NumOccurrences(strLine, " And ")
  345.         uStat.Metric(ROUTINEDECPTS) = uStat.Metric(ROUTINEDECPTS) + intDecPts
  346.         uStat.CurrentComplexity = uStat.CurrentComplexity + intDecPts
  347.         
  348.         intDecPts = NumOccurrences(strLine, " Or ")
  349.         uStat.Metric(ROUTINEDECPTS) = uStat.Metric(ROUTINEDECPTS) + intDecPts
  350.         uStat.CurrentComplexity = uStat.CurrentComplexity + intDecPts
  351.     
  352.     End If
  353.     
  354. End Sub
  355.  
  356. Function DisplayMetric (intIdx As Integer) As Integer
  357.  
  358.     DisplayMetric = muaMetric(intIdx).Display
  359.  
  360. End Function
  361.  
  362. Function Filename (strPath As String) As String
  363.  
  364. ' Remove all the path stuff from a pathname
  365.  
  366. Dim intStart
  367.  
  368.     ' If no path in string, that's it
  369.     If InStr(strPath, "\") = 0 Then
  370.         Filename = strPath
  371.         Exit Function
  372.     End If
  373.  
  374.     ' Work back from end until \ found, then return the RHS
  375.     For intStart = Len(strPath) To 1 Step -1
  376.         If Mid$(strPath, intStart, 1) = "\" Then
  377.             intStart = intStart + 1
  378.             Filename = Mid$(strPath, intStart)
  379.             Exit Function
  380.         End If
  381.     Next
  382.  
  383.     Filename = "#ERROR#"
  384.  
  385. End Function
  386.  
  387. Sub FillFileList (lst As Control)
  388.  
  389. Dim i As Integer
  390.  
  391.     lst.Clear
  392.  
  393.     For i = LBound(mstraProjFile) To UBound(mstraProjFile)
  394.         If Len(mstraProjFile(i)) > 0 Then
  395.             lst.AddItem mstraProjFile(i)
  396.         End If
  397.     Next
  398.  
  399. End Sub
  400.  
  401. Sub GetProjectToUse (dlg As CommonDialog)
  402.  
  403. ' Use common dialog to get a .MAK file
  404.  
  405.     dlg.DialogTitle = "Open Project"
  406.     dlg.Filter = "VB Project (*.mak)|*.mak|All files (*.*)|*.*"
  407.     dlg.Flags = OFN_FILEMUSTEXIST
  408.     dlg.Action = DLG_FILE_OPEN
  409.  
  410.     If dlg.Filename <> "" Then
  411.         mstrProjectName = dlg.Filename
  412.         mblnProjectSelected = True
  413.     Else
  414.         mblnProjectSelected = False
  415.     End If
  416.  
  417. End Sub
  418.  
  419. Sub inc (uStat As FileStats_Type, intMetricIdx As Integer)
  420.  
  421. ' increment a specified metric within a FileStats_Type
  422.  
  423.     uStat.Metric(intMetricIdx) = uStat.Metric(intMetricIdx) + 1
  424.  
  425. End Sub
  426.  
  427. Sub Initialise ()
  428.  
  429.     mblnProjectSelected = False
  430.     mstrProjectName = ""
  431.  
  432.     ReDim mstraProjFile(1 To 1)
  433.  
  434.     ' keep to 8 chars or less
  435.     muaMetric(TOTSIZE).Name = "TotBytes"
  436.     muaMetric(TOTLINES).Name = "TotLines"
  437.     muaMetric(BLANKLINES).Name = "Blanks"
  438.     muaMetric(TOTCOMMENTS).Name = "Comments"
  439.     muaMetric(TOTROUTINES).Name = "Routines"
  440.     muaMetric(PRIVATEROUTINES).Name = "PrivRtns"
  441.     muaMetric(LOCALVARS).Name = "LocVars"
  442.     muaMetric(LOCALCONSTS).Name = "LocCnst"
  443.     muaMetric(MODULEVARS).Name = "ModVars"
  444.     muaMetric(MODULECONSTS).Name = "ModCnst"
  445.     muaMetric(GLOBALVARS).Name = "GblVars"
  446.     muaMetric(GLOBALCONSTS).Name = "GlbCnst"
  447.     muaMetric(APIDECS).Name = "APIs"
  448.     muaMetric(TYPES).Name = "Types"
  449.     muaMetric(TYPELINES).Name = "TypLns"
  450.     muaMetric(AVERTNLINES).Name = "AveRtLns"
  451.     muaMetric(RTNNONCODELINES).Name = "NonCdLns"
  452.     muaMetric(ROUTINECODELINES).Name = "RtnCdLns"
  453.     muaMetric(ROUTINEDECPTS).Name = "RtDecPts"
  454.     muaMetric(MOSTCOMPLEX).Name = "MostDPs"
  455.  
  456.     muaMetric(TOTSIZE).Display = True
  457.     muaMetric(TOTLINES).Display = True
  458.     muaMetric(BLANKLINES).Display = True
  459.     muaMetric(TOTCOMMENTS).Display = True
  460.     muaMetric(TOTROUTINES).Display = True
  461.     muaMetric(PRIVATEROUTINES).Display = True
  462.     muaMetric(LOCALVARS).Display = False
  463.     muaMetric(LOCALCONSTS).Display = False
  464.     muaMetric(MODULEVARS).Display = True
  465.     muaMetric(MODULECONSTS).Display = False
  466.     muaMetric(GLOBALVARS).Display = True
  467.     muaMetric(GLOBALCONSTS).Display = True
  468.     muaMetric(APIDECS).Display = False
  469.     muaMetric(TYPES).Display = False
  470.     muaMetric(TYPELINES).Display = False
  471.     muaMetric(AVERTNLINES).Display = True
  472.     muaMetric(RTNNONCODELINES).Display = True
  473.     muaMetric(ROUTINECODELINES).Display = True
  474.     muaMetric(ROUTINEDECPTS).Display = True
  475.     muaMetric(MOSTCOMPLEX).Display = True
  476.  
  477.     muaMetric(TOTSIZE).LongName = "Total File Bytes"
  478.     muaMetric(TOTLINES).LongName = "Total # Lines"
  479.     muaMetric(BLANKLINES).LongName = "Blank Lines"
  480.     muaMetric(TOTCOMMENTS).LongName = "Comments"
  481.     muaMetric(TOTROUTINES).LongName = "Routines"
  482.     muaMetric(PRIVATEROUTINES).LongName = "Private Rtns"
  483.     muaMetric(LOCALVARS).LongName = "Local Vars"
  484.     muaMetric(LOCALCONSTS).LongName = "Local Consts"
  485.     muaMetric(MODULEVARS).LongName = "Module Vars"
  486.     muaMetric(MODULECONSTS).LongName = "Module Constants"
  487.     muaMetric(GLOBALVARS).LongName = "Global Vars"
  488.     muaMetric(GLOBALCONSTS).LongName = "Global Consts"
  489.     muaMetric(APIDECS).LongName = "API Decl's"
  490.     muaMetric(TYPES).LongName = "Type Definitions"
  491.     muaMetric(TYPELINES).LongName = "Type Lines"
  492.     muaMetric(AVERTNLINES).LongName = "Ave Lines/Routine"
  493.     muaMetric(RTNNONCODELINES).LongName = "Non-Code Routine Lines"
  494.     muaMetric(ROUTINECODELINES).LongName = "Routine Code Lines"
  495.     muaMetric(ROUTINEDECPTS).LongName = "Routine Decision Points"
  496.     muaMetric(MOSTCOMPLEX).LongName = "Most Complex Dec Pts"
  497.  
  498. End Sub
  499.  
  500. Function IsLeftEnd (strToCheck, strToFind) As Integer
  501.  
  502. Dim intLen As Integer
  503.  
  504.     intLen = Len(strToFind) + 1
  505.  
  506.     If Left$(strToCheck, intLen) = strToFind & " " Or Left$(strToCheck, intLen) = strToFind Then
  507.         IsLeftEnd = True
  508.     Else
  509.         IsLeftEnd = False
  510.     End If
  511.  
  512. End Function
  513.  
  514. Function IsRoutine (strLine) As Integer
  515.  
  516.     If LeftMostWord(strLine) = "Sub" Then
  517.         IsRoutine = True
  518.     ElseIf LeftMostWord(strLine) = "Function" Then
  519.         IsRoutine = True
  520.     Else
  521.         IsRoutine = False
  522.     End If
  523.  
  524. End Function
  525.  
  526. Function IsUserProjectFile (strFile As String) As Integer
  527.  
  528. Dim strExt As String
  529.  
  530.     strExt = Right$(strFile, 3)
  531.     If strExt = "BAS" Then
  532.         IsUserProjectFile = True
  533.     ElseIf strExt = "FRM" Then
  534.         IsUserProjectFile = True
  535.     Else
  536.         IsUserProjectFile = False
  537.     End If
  538.  
  539. End Function
  540.  
  541. Function MetricLongName (intIdx As Integer) As String
  542.  
  543.     MetricLongName = muaMetric(intIdx).LongName
  544.  
  545. End Function
  546.  
  547. Function MetricName (intIdx) As String
  548.  
  549.     MetricName = muaMetric(intIdx).Name
  550.  
  551. End Function
  552.  
  553. Function MetricsInUse () As Integer
  554.  
  555. Dim i As Integer
  556. Dim intCount As Integer
  557.  
  558.     For i = LBound(muaMetric) To UBound(muaMetric)
  559.         If muaMetric(i).Display Then
  560.             intCount = intCount + 1
  561.         End If
  562.     Next
  563.  
  564.     MetricsInUse = intCount
  565.  
  566. End Function
  567.  
  568. Function MetricValue (uStat As FileStats_Type, intIdx As Integer) As Single
  569.  
  570. Dim sngValue As Single
  571.  
  572.     sngValue = uStat.Metric(intIdx)
  573.  
  574.     If Int(sngValue) <> sngValue Then
  575.         sngValue = Int(sngValue * 100) / 100
  576.     End If
  577.  
  578.     MetricValue = sngValue
  579.  
  580. End Function
  581.  
  582. Function NumMetrics () As Integer
  583.  
  584. Dim intCount As Integer
  585. Dim intIdx As Integer
  586.  
  587.     For intIdx = LBound(muaMetric) To UBound(muaMetric)
  588.         If Len(muaMetric(intIdx).Name) > 0 Then
  589.             intCount = intCount + 1
  590.         End If
  591.     Next
  592.  
  593.     NumMetrics = intCount
  594.  
  595. End Function
  596.  
  597. Sub OpenProject (lst As Control, dlg As CommonDialog)
  598.  
  599.     ClearProjectFileList
  600.  
  601. ' Find out what project is to be analysed
  602.     GetProjectToUse dlg
  603.  
  604. ' If a project was selected, alter the caption to reflect this
  605.     If ProjectSelected() Then
  606.         SetFormCaption frmMain
  607.     Else
  608.         ResetFormCaption frmMain
  609.     End If
  610.  
  611.     OpenProjectFile
  612.     FillFileList lst
  613.  
  614. End Sub
  615.  
  616. Sub OpenProjectFile ()
  617.  
  618. Dim intF As Integer
  619. Dim strLine As String
  620. Dim strProj As String
  621.  
  622.     intF = FreeFile
  623.  
  624.     strProj = ProjectName()
  625.  
  626.     If Len(strProj) <= 0 Then
  627.         Exit Sub
  628.     End If
  629.  
  630.     Open ProjectName() For Input As intF
  631.  
  632.     Do
  633.         Input #intF, strLine
  634.         If IsUserProjectFile(strLine) Then
  635.             StoreProjectFile strLine
  636.         End If
  637.     Loop Until EOF(intF)
  638.  
  639.     Close intF
  640.  
  641. End Sub
  642.  
  643. Sub PrintResults (grd As Grid)
  644.  
  645. Dim lngRow As Long
  646. Dim lngCol As Long
  647. Dim strOut As String
  648.  
  649.     Printer.FontSize = 8
  650.  
  651.     Screen.MousePointer = HOURGLASS
  652.  
  653.     Printer.CurrentX = 200
  654.     Printer.Print ProjectName()
  655.     Printer.Print
  656.  
  657.     For lngRow = 0 To grd.Rows - 1
  658.  
  659.         Printer.CurrentX = 200
  660.         strOut = RPad(GridText(grd, 0, lngRow), 12)
  661.         Printer.Print strOut;
  662.  
  663.         For lngCol = 1 To grd.Cols - 1
  664.             If lngCol < grd.Cols - 1 Then
  665.                 strOut = Space$(9)
  666.                 RSet strOut = GridText(grd, lngCol, lngRow)
  667.             Else
  668.                 strOut = " " & GridText(grd, lngCol, lngRow)
  669.             End If
  670.             Printer.Print strOut;
  671.  
  672.         Next
  673.         Printer.Print
  674.     Next
  675.  
  676.     Printer.EndDoc
  677.  
  678.     Screen.MousePointer = DEFAULT
  679.  
  680. End Sub
  681.  
  682. Function ProjectName () As String
  683.  
  684.     ProjectName = mstrProjectName
  685.  
  686. End Function
  687.  
  688. Function ProjectSelected () As Integer
  689.  
  690.     ProjectSelected = mblnProjectSelected
  691.  
  692. End Function
  693.  
  694. Sub ReopenProject (lst As Control)
  695.  
  696.     ClearProjectFileList
  697.  
  698.     OpenProjectFile
  699.     FillFileList lst
  700.  
  701. End Sub
  702.  
  703. Sub ReportStats (uStat As FileStats_Type, grd As Grid)
  704.  
  705. Dim lngRow As Long
  706. Dim lngCols As Long
  707. Dim strClip As String
  708. Dim cTAB As String * 1
  709. Dim i As Integer
  710.  
  711.     cTAB = Chr$(9)
  712.     
  713.     If uStat.Metric(TOTROUTINES) > 0 Then
  714.         uStat.Metric(AVERTNLINES) = (uStat.Metric(ROUTINECODELINES) + uStat.Metric(RTNNONCODELINES)) / uStat.Metric(TOTROUTINES)
  715.     End If
  716.  
  717.     If DisplayMetric(MOSTCOMPLEX) Then
  718.         lngCols = MetricsInUse() + 2
  719.     Else
  720.         lngCols = MetricsInUse() + 1
  721.     End If
  722.  
  723.     grd.Cols = lngCols
  724.     grd.Rows = grd.Rows + 1
  725.     lngRow = grd.Rows - 1
  726.  
  727.     strClip = uStat.Filename & "|"
  728.  
  729.     For i = 1 To NumMetrics()
  730.         If DisplayMetric(i) Then
  731.             strClip = strClip & MetricValue(uStat, i) & "|"
  732.         End If
  733.     Next
  734.  
  735.     If DisplayMetric(MOSTCOMPLEX) Then
  736.         strClip = strClip & uStat.WorstRoutine
  737.     End If
  738.  
  739.     Replace strClip, "|", cTAB
  740.  
  741.     SetGridClip grd, lngRow, 0, 1, (grd.Cols), strClip
  742.  
  743. End Sub
  744.  
  745. Sub ResetFormCaption (frm As Form)
  746.  
  747.     frm.Caption = APP_NAME
  748.  
  749. End Sub
  750.  
  751. Sub SetFormCaption (frm As Form)
  752.  
  753.     frm.Caption = APP_NAME & "(" & ProjectName() & ")"
  754.  
  755. End Sub
  756.  
  757. Sub SetGridHeadings (grd As Grid)
  758.  
  759. Dim i As Integer
  760. Dim lngCurrCol As Long
  761. Dim strHdg As String
  762. Dim cTAB As String * 1
  763.  
  764.     cTAB = Chr$(9)
  765.  
  766.     grd.Cols = MetricsInUse() + 1
  767.     grd.Cols = grd.Cols + IIf(DisplayMetric(MOSTCOMPLEX), 1, 0)
  768.  
  769.     strHdg = "FileName|"
  770.  
  771.     grd.ColWidth(0) = frmMain.TextWidth("nnnnnnnnnnnn")
  772.  
  773.     lngCurrCol = 1
  774.     For i = 1 To NumMetrics()
  775.         If DisplayMetric(i) Then
  776.             grd.ColWidth(lngCurrCol) = frmMain.TextWidth("nnnnnn")
  777.             grd.ColAlignment(lngCurrCol) = 1
  778.             strHdg = strHdg & MetricName(i) & "|"
  779.             lngCurrCol = lngCurrCol + 1
  780.         End If
  781.     Next
  782.  
  783.     If DisplayMetric(MOSTCOMPLEX) Then
  784.         grd.ColWidth(lngCurrCol) = frmMain.TextWidth("nnnnnnnnnnnnnnnn")
  785.         strHdg = strHdg & "WorstRtn"
  786.     End If
  787.  
  788.     Replace strHdg, "|", cTAB
  789.  
  790.     SetGridClip grd, 0, 0, 1, grd.Cols, strHdg
  791.  
  792. End Sub
  793.  
  794. Sub SetMetricDisplay (intIdx As Integer, ByVal intVal As Integer)
  795.  
  796.     muaMetric(intIdx).Display = intVal
  797.  
  798. End Sub
  799.  
  800. Sub StoreProjectFile (strFile As String)
  801.  
  802.     ' If last entry in array is already in use
  803.     If Len(mstraProjFile(UBound(mstraProjFile))) > 0 Then
  804.         ' Resize array to add another slot
  805.         ReDim Preserve mstraProjFile(LBound(mstraProjFile) To UBound(mstraProjFile) + 1)
  806.     End If
  807.     
  808.     ' Now use the new slot
  809.     mstraProjFile(UBound(mstraProjFile)) = strFile
  810.         
  811. End Sub
  812.  
  813. Sub StripLeftmostWord (strIn As String)
  814.  
  815.     If InStr(strIn, " ") = 0 Then
  816.         strIn = ""
  817.     Else
  818.         strIn = Trim$(Mid$(strIn, InStr(strIn, " ")))
  819.     End If
  820.  
  821. End Sub
  822.  
  823. Sub Terminate ()
  824.  
  825. ' Handle any special termination processing here
  826.  
  827. End Sub
  828.  
  829. Sub ZeroProjectTotals ()
  830.  
  831. Dim i As Integer
  832.  
  833.     muTotStat.Filename = "Totals"
  834.     For i = LBound(muTotStat.Metric) To UBound(muTotStat.Metric)
  835.         muTotStat.Metric(i) = 0
  836.     Next
  837.  
  838. End Sub
  839.  
  840.